home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Util / conv / Acvt.lha / Acvt 1.07 / sources / adsk_atr.cpp < prev    next >
C/C++ Source or Header  |  2001-03-08  |  9KB  |  484 lines

  1. //    This program is free software; you can redistribute it and/or modify
  2. //    it under the terms of the GNU General Public License as published by
  3. //    the Free Software Foundation; either version 2 of the License, or
  4. //    any later version.
  5. //
  6. //    This program is distributed in the hope that it will be useful,
  7. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9. //    GNU General Public License for more details.
  10. //
  11. //    You should have received a copy of the GNU General Public License
  12. //    along with this program; if not, write to the Free Software
  13. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. //
  15.  
  16. #include "adsk_atr.h"
  17. #include "autil.h"
  18. #include "cfile.h"
  19.  
  20. #define ATR_MAGIC 0x0296
  21.  
  22. typedef struct
  23. {
  24.     WORD    wMagic;
  25.     WORD    wPars;
  26.     WORD    wSecSize;
  27.     BYTE    btParHigh;
  28.     DWORD dwCRC;
  29.     DWORD dwUnused;
  30.     BYTE    btFlags;
  31.  
  32. } ATRhead;
  33.  
  34. #define ATR_HEAD_LEN 0x10
  35.  
  36. CAtr::CAtr() : ADisk()
  37. {
  38.     #ifdef _MEMORY_DUMP_
  39.         printf( "CAtr constructed: %p\n", this );
  40.     #endif
  41. }
  42.  
  43. CAtr::~CAtr()
  44. {
  45.     #ifdef _MEMORY_DUMP_
  46.         printf( "CAtr destructed: %p\n", this );
  47.     #endif
  48. }
  49.  
  50. typedef enum
  51. {
  52.     LOAD_OK,
  53.     LOAD_BAD_DD_1,
  54.     LOAD_BAD_DD_2,
  55.     LOAD_BAD_DD_3,
  56.     LOAD_PAD
  57. } LOAD_VARIANT;
  58.  
  59. #ifndef __CDISK_NOLOAD__
  60. BOOL CAtr::Load( char* szFname, BOOL bRepair, BOOL bRepairAuto )
  61. {
  62.     LOAD_VARIANT load_method = LOAD_OK;    
  63.  
  64.     m_iErrorCode = 0;
  65.  
  66.     int iFirstSectorsSize = 0x80;
  67.  
  68.     CFile cf;
  69.  
  70.     if ( !cf.Open( szFname ) )
  71.     {
  72.         sprintf( m_szLastError, "ATR: Can't open '%s'", szFname );
  73.         m_iErrorCode = CDISK_ERROR_CANT_OPEN;
  74.         return FALSE;
  75.     }
  76.  
  77.     strcpy( m_szFname, szFname );
  78.  
  79.     ATRhead head;
  80.  
  81.     head.wMagic            =    cf.readLEw();    
  82.     head.wPars            =    cf.readLEw();    
  83.     head.wSecSize        =    cf.readLEw();    
  84.     head.btParHigh        =    cf.readb();    
  85.     head.dwCRC            =    cf.readLEdw(); 
  86.     head.dwUnused        =    cf.readLEdw(); 
  87.     head.btFlags        =    cf.readb();    
  88.  
  89.     if ( head.wMagic != ATR_MAGIC )
  90.     {
  91.         sprintf( m_szLastError, "ATR: File '%s' is not an ATR file!", szFname );
  92.         return FALSE;
  93.     }
  94.  
  95.     LONG lFileLen = cf.GetLength();
  96.     cf.Seek( ATR_HEAD_LEN, SEEK_SET );
  97.  
  98.     switch( head.wSecSize )
  99.     {
  100.         case 0x80:
  101.         case 0x100:
  102.             break;
  103.  
  104.         default:
  105.         {
  106.             sprintf( m_szLastError, "ATR: Invalid sector size: %04X", head.wSecSize );
  107.             return FALSE;
  108.         }
  109.     }
  110.  
  111.     DWORD dwPars = head.wPars | ( head.btParHigh << 16 );
  112.  
  113.     int iSectors = ( dwPars * 0x10 ) / head.wSecSize;
  114.  
  115.     //BOOL bReadOnly = (head.btFlags & 1) ? TRUE : FALSE;
  116.  
  117.     if ( head.wSecSize == 0x100 )
  118.     {
  119.         //if ( dwPars % head.wSecSize )
  120.         if ( ( dwPars * 0x10 ) % head.wSecSize )
  121.         {
  122.             iSectors = ( ( dwPars * 0x10 - 0x180 ) / head.wSecSize ) + 3;
  123.         }
  124.         else
  125.         {
  126.             sprintf( m_szLastError, "ATR: Format violated. First three sectors are not $80 long!" );
  127.             m_iErrorCode = CATR_FORMAT_VIOLATED;
  128.  
  129.             #ifdef __CDISK_NOREPAIR__
  130.                 return FALSE;
  131.             #else
  132.             if ( !bRepair )
  133.             {
  134.                 return FALSE;
  135.             }
  136.             else
  137.             {
  138.                 BYTE abtBuff[ 0x100 ];
  139.  
  140.                 memset( abtBuff, 0, 0x100 );
  141.  
  142.                 int iM1zeroes = 3;
  143.                 int iM2zeroes = 3;
  144.                 int iM3zeroes = 3;
  145.  
  146.                 cf.Seek( ATR_HEAD_LEN + ( 0x02 - 1 ) * 0x80, SEEK_SET );
  147.                 cf.Read( abtBuff, 0x80 );
  148.  
  149.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  150.                     iM1zeroes--;
  151.  
  152.                 cf.Seek( ATR_HEAD_LEN + ( 0x04 - 1 ) * 0x80, SEEK_SET );
  153.                 cf.Read( abtBuff, 0x80 );
  154.  
  155.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  156.                 {
  157.                     iM1zeroes--;
  158.                     iM2zeroes--;
  159.                 }
  160.  
  161.                 cf.Seek( ATR_HEAD_LEN + ( 0x05 - 1 ) * 0x80, SEEK_SET );
  162.                 cf.Read( abtBuff, 0x80 );
  163.  
  164.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  165.                     iM2zeroes--;
  166.  
  167.                 cf.Seek( ATR_HEAD_LEN + ( 0x06 - 1 ) * 0x80, SEEK_SET );
  168.                 cf.Read( abtBuff, 0x80 );
  169.  
  170.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  171.                 {
  172.                     iM1zeroes--;
  173.                     iM2zeroes--;
  174.                 }
  175.  
  176.                 cf.Seek( -0x180, SEEK_END );
  177.                 cf.Read( abtBuff, 0x80 );
  178.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  179.                     iM3zeroes--;
  180.  
  181.                 cf.Read( abtBuff, 0x80 );
  182.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  183.                     iM3zeroes--;
  184.  
  185.                 cf.Read( abtBuff, 0x80 );
  186.                 if ( IsBlockEmpty( abtBuff, 0x80 ) )
  187.                     iM3zeroes--;
  188.  
  189.                 if ( !iM1zeroes )
  190.                 {
  191.                     load_method = LOAD_BAD_DD_1;
  192.                 }
  193.                 else if ( !iM2zeroes )
  194.                 {
  195.                     load_method = LOAD_BAD_DD_2;
  196.                 }
  197.                 else if ( !iM3zeroes )
  198.                 {
  199.                     load_method = LOAD_BAD_DD_3;
  200.                 }
  201.  
  202.                 if ( !bRepairAuto )
  203.                 {
  204.                     printf( "Invalid DD ATR file encountered.\n" );
  205.                     printf( "Choose repair method:\n" );
  206.                     printf( "1) Sector, gap, sector, gap, sector, gap, data\n" );
  207.                     printf( "2) Three sectors, three empty sectors, data\n" );
  208.                     printf( "3) Data, three empty sectors\n" );
  209.                     printf( "4) Don't repair\n" );
  210.  
  211.                     switch( load_method )
  212.                     {
  213.                         case LOAD_BAD_DD_1:
  214.                             printf( "(Method 1 looks best)\n" );
  215.                             break;
  216.  
  217.                         case LOAD_BAD_DD_2:
  218.                             printf( "(Method 2 looks best)\n" );
  219.                             break;
  220.  
  221.                         case LOAD_BAD_DD_3:
  222.                             printf( "(Method 3 looks best)\n" );
  223.                             break;
  224.  
  225.                         default:
  226.                             break;
  227.                     }
  228.  
  229.                     int iMethod;
  230.  
  231.                     printf( "\n" );
  232.                     do
  233.                     {
  234.                         iMethod = getch() - '0';
  235.                     } while( ( iMethod < 1 ) || ( iMethod > 4 ) );
  236.  
  237.                     switch( iMethod )
  238.                     {
  239.                         case 1:
  240.                             load_method = LOAD_BAD_DD_1;
  241.                             break;
  242.                         case 2:
  243.                             load_method = LOAD_BAD_DD_2;
  244.                             break;
  245.                         case 3:
  246.                             load_method = LOAD_BAD_DD_3;
  247.                             break;
  248.                         default:
  249.                         case 4:
  250.                             return FALSE;
  251.                             break;
  252.                     }
  253.                 }
  254.                 else
  255.                 {
  256.                     if ( load_method == LOAD_OK )
  257.                         load_method = LOAD_BAD_DD_1;
  258.                 }
  259.  
  260.  
  261.                 cf.Seek( ATR_HEAD_LEN, SEEK_SET );
  262.  
  263.                 switch( load_method )
  264.                 {
  265.                     case LOAD_BAD_DD_1:
  266.                     case LOAD_BAD_DD_2:
  267.                     case LOAD_BAD_DD_3:
  268.                         iFirstSectorsSize = 0x100;
  269.                         break;
  270.  
  271.                     default:
  272.                         break;
  273.                         
  274.                 }
  275.                     
  276.             } //end of repair
  277.  
  278.             #endif
  279.         }
  280.     }
  281.  
  282.     LONG lTotalComputedLen = (LONG) ( ( iSectors - 3 ) * head.wSecSize + ATR_HEAD_LEN + 3 * iFirstSectorsSize );
  283.  
  284.     if ( lTotalComputedLen != lFileLen )
  285.     {
  286.         sprintf( m_szLastError, "ATR: Invalid length! %08lX <> %08lX (%08X)", lTotalComputedLen, lFileLen, iSectors );
  287.         m_iErrorCode = CATR_FORMAT_VIOLATED;
  288.  
  289.         #ifdef __CDISK_NOREPAIR__
  290.             return FALSE;
  291.         #else
  292.         if ( !bRepair || ( load_method != LOAD_OK ) )
  293.             return FALSE;
  294.         else
  295.         {
  296.             if ( !bRepairAuto )
  297.             {
  298.                 printf( "ATR with invalid length encountered.\n" );
  299.                 printf( "Should be: $%08lX. Is: $%08lX.\n", lTotalComputedLen, lFileLen );
  300.                 printf( "Choose:\n" );
  301.                 printf( "1) Change file length (shorten/pad)\n" );
  302.                 printf( "2) Change header info\n" );
  303.                 printf( "3) Don't repair\n" );
  304.  
  305.                 int iMethod;
  306.  
  307.                 do
  308.                 {
  309.                     iMethod = getch() - '0';
  310.                 } while( ( iMethod < 1 ) || ( iMethod > 3 ) );
  311.  
  312.                 switch( iMethod )
  313.                 {
  314.                     case 1:
  315.                         load_method = LOAD_PAD;
  316.                         break;
  317.  
  318.                     case 2:
  319.                         load_method = LOAD_OK;
  320.                         if ( lFileLen > 0x180 )
  321.                         {
  322.                             iSectors = ( ( lFileLen - 0x180 ) / head.wSecSize ) + 3;
  323.                         }
  324.                         else
  325.                         {
  326.                             iSectors = lFileLen / 0x80;
  327.                         }
  328.  
  329.                         break;
  330.  
  331.                     default:
  332.                     case 3:
  333.                         return FALSE;
  334.                         break;
  335.                 }
  336.             }
  337.             else
  338.             {
  339.                 if ( load_method == LOAD_OK )
  340.                     load_method = LOAD_PAD;
  341.             }
  342.  
  343.         }
  344.         #endif
  345.  
  346.     }
  347.  
  348.     DISK_GEOMETRY dg;
  349.  
  350.     GuessClassicSizes( iSectors, head.wSecSize, &dg );
  351.  
  352.     if ( !Format( &dg ) )
  353.         return FALSE;
  354.  
  355.     BYTE abtBuff[ 0x100 ];
  356.     memset( abtBuff, 0, 0x100 );
  357.  
  358.     for( int i = 0; i < iSectors; i++ )
  359.     {
  360.         switch( load_method )
  361.         {
  362.             default:
  363.             case LOAD_OK:
  364.                 cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize );
  365.                 break;
  366.  
  367.             case LOAD_PAD:
  368.                 memset( abtBuff, 0, 0x100 );
  369.                 cf.Read( abtBuff, ( i < 3 ) ? 0x80 : head.wSecSize );
  370.                 break;
  371.  
  372.             case LOAD_BAD_DD_1:
  373.                 if ( i < 3 )
  374.                 {
  375.                     cf.Read( abtBuff, 0x80 );
  376.                     cf.Seek( 0x80, SEEK_CUR );
  377.                 }
  378.                 else
  379.                     cf.Read( abtBuff, 0x100 );
  380.                 break;
  381.  
  382.             case LOAD_BAD_DD_2:
  383.                 if ( i < 3 )
  384.                 {
  385.                     cf.Read( abtBuff, 0x80 );
  386.  
  387.                     if ( i == 2 )
  388.                         cf.Seek( 0x180, SEEK_CUR );
  389.                 }
  390.                 else
  391.                     cf.Read( abtBuff, 0x100 );
  392.  
  393.                 break;
  394.  
  395.             case LOAD_BAD_DD_3:
  396.                 if ( i < 3 )
  397.                     cf.Read( abtBuff, 0x80 );
  398.                 else
  399.                     cf.Read( abtBuff, 0x100 );
  400.  
  401.                 break;
  402.         }
  403.  
  404.         WriteSector( i + 1, abtBuff );
  405.     }
  406.  
  407.     cf.Close();
  408.     return TRUE;
  409.  
  410. }
  411.  
  412. #endif
  413.  
  414. #ifdef __CDISK_SAVE__
  415.  
  416. BOOL CAtr::Save( char* szOutFile, BOOL bOverWrite )
  417. {
  418.     CFile cf;
  419.  
  420.     if ( !bOverWrite && !access( szOutFile, F_OK ) )
  421.     {
  422.         sprintf( m_szLastError, "ATR: File already exists! '%s'", szOutFile );
  423.         return FALSE;
  424.     }
  425.  
  426.     if ( !cf.Create( szOutFile ) )
  427.     {
  428.         sprintf( m_szLastError, "ATR: Can't create '%s'", szOutFile );
  429.         return FALSE;
  430.     }
  431.  
  432.     ATRhead head;
  433.     memset( &head, 0, sizeof( ATRhead ) );
  434.  
  435.     head.wMagic = ATR_MAGIC;
  436.     head.wSecSize = m_geometry.iBytesPerSector;
  437.  
  438.     BOOL bReadOnly = TRUE;
  439.     head.btFlags |= ( bReadOnly ) ? 0x01 : 0x00;
  440.  
  441.     DWORD dwLength = 0;
  442.  
  443.     dwLength = 0x180 + ( m_geometry.iSectors - 3 ) * m_geometry.iBytesPerSector;
  444.  
  445.     dwLength >>= 4;
  446.  
  447.     head.wPars = dwLength & 0xFFFF;
  448.     head.btParHigh = dwLength >> 0x10;
  449.  
  450.     cf.writeLEw( head.wMagic );    
  451.     cf.writeLEw( head.wPars );    
  452.     cf.writeLEw( head.wSecSize );    
  453.     cf.writeb( head.btParHigh );    
  454.     cf.writeLEdw( head.dwCRC ); 
  455.     cf.writeLEdw( head.dwUnused    ); 
  456.     cf.writeb( head.btFlags );    
  457.  
  458.     BYTE abtBuff[ 0x100 ];
  459.  
  460.     for( WORD i = 1; i <= m_geometry.iSectors; i++ )
  461.     {
  462.         ReadSector( abtBuff, i );
  463.  
  464.         int iToWrite = ( i <= 3 ) ? 0x80: m_geometry.iBytesPerSector;
  465.  
  466.         int iWritten;
  467.  
  468.         if ( !cf.Write( abtBuff, iToWrite, &iWritten ) || ( iToWrite != iWritten ) )
  469.         {
  470.             sprintf( m_szLastError, "ATR: Can't write!" );
  471.             cf.Close();
  472.             unlink( szOutFile );
  473.             return FALSE;
  474.             
  475.         }
  476.     }
  477.  
  478.     cf.Close();
  479.  
  480.     return TRUE;
  481. }
  482.  
  483. #endif //__CDISK_WRITE__
  484.